#include <QtGui>
#include <iostream>
#include "codeeditor.h"
#include "mainwindow.h"
#include <QToolTip>
#include <QThread>
#include <QScrollBar>

CodeEditor::CodeEditor(QWidget *parent, MainWindow *mainWindowHandler) : QPlainTextEdit(parent)
{
    mainWindow = mainWindowHandler;
    lineNumberArea = new LineNumberArea(this);
    syntaxHighlighter = new SyntaxHighlighter(this->document());

    connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
    connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
    connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightMatchingBrackets);
    //connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));

    connect(this, &CodeEditor::cursorPositionChanged, this, [=] {
                if(syntaxHighlighter->showErrorHighLight) {
                    syntaxHighlighter->showErrorHighLight = 0;
                    syntaxHighlighter->rehighlight();
                }
                // 在这里添加你希望执行的代码
            });

    //connect(verticalScrollBar(), &QScrollBar::valueChanged, this, [=] {repaint();});
    //connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, [=] {repaint();});

    updateLineNumberAreaWidth(0);
    //highlightCurrentLine();

}



int CodeEditor::lineNumberAreaWidth()
{
    int digits = 1;
    int max = qMax(1, blockCount());
    while (max >= 10) {
        max /= 10;
        ++digits;
    }

    int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;

    int charWidth = 25;
    if(mainWindow && mainWindow->tabManager && mainWindow->tabManager->toolsSettings) {
        QFontMetrics fm(mainWindow->tabManager->toolsSettings->currentFont);
        charWidth = fm.horizontalAdvance('A');
    }
    return std::max(space + charWidth * 2, 50);
}

void CodeEditor::loadBackgroundImage(QString imagePath, qreal opacity1)
{
    if (!imagePath.isEmpty()) {
         setBackgroundImage(imagePath); // 设置背景图片

    }
    setBackgroundOpacity(opacity1); // 设置不透明度
    update();
}

void CodeEditor::setBackgroundImage(const QString &imagePath)
{
    backgroundImage = new QPixmap(imagePath); // 加载图片
    /*if (backgroundImage->isNull()) {
        qDebug() << "Failed to load image from path:" << imagePath;
    }
    std::cout << imagePath.toStdString() << std::endl;

    la.resize(backgroundImage->size());
    la.setPixmap(*backgroundImage);
    la.show();*/
}

void CodeEditor::setBackgroundOpacity(qreal newOpacity)
{
    opacity = newOpacity; // 设置不透明度
}


void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
{
    setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}



void CodeEditor::updateLineNumberArea(const QRect &rect, int dy)
{
    if (dy)
        lineNumberArea->scroll(0, dy);
    else
        lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());

    if (rect.contains(viewport()->rect()))
        updateLineNumberAreaWidth(0);
}



void CodeEditor::resizeEvent(QResizeEvent *e)
{
    QPlainTextEdit::resizeEvent(e);

    QRect cr = contentsRect();
    lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}


/*
void CodeEditor::highlightCurrentLine()
{
    QList<QTextEdit::ExtraSelection> extraSelections;

    if (!isReadOnly()) {
        QTextEdit::ExtraSelection selection;

        QColor lineColor = QColor("greenyellow").lighter(160);

        selection.format.setBackground(lineColor);
        selection.format.setProperty(QTextFormat::FullWidthSelection, true);
        selection.cursor = textCursor();
        selection.cursor.clearSelection();
        extraSelections.append(selection);
    }

    setExtraSelections(extraSelections);
}

void CodeEditor::clearHighlightCurrentLine()
{
        setExtraSelections(QList<QTextEdit::ExtraSelection>());
}
*/
void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event)
{
    QPainter painter(lineNumberArea);
    painter.fillRect(event->rect(), Qt::lightGray);


    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();

    while (block.isValid() && top <= event->rect().bottom()) {
        if (block.isVisible() && bottom >= event->rect().top()) {
            QString number = QString::number(blockNumber + 1);
            painter.setPen(Qt::black);
            painter.setFont(font());
            /*painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
                             Qt::AlignRight, number);*/
            painter.drawText(0, top, lineNumberArea->width() - 20, fontMetrics().height(),
                                             Qt::AlignLeft, number);
        }

        // 绘制叹号标志
        for (const auto &info : syntaxHighlighter->errorInfo) {
            if (info.first.first == blockNumber + 1) {
                painter.setPen(Qt::red);
                painter.setFont(font());
                /*painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
                Qt::AlignLeft, "⚠️");*/
                int charWidth = 25;
                if(mainWindow && mainWindow->tabManager && mainWindow->tabManager->toolsSettings) {
                    QFontMetrics fm(mainWindow->tabManager->toolsSettings->currentFont);
                    charWidth = fm.horizontalAdvance('A');
                }
                painter.drawText(lineNumberArea->width() - charWidth * 2, top, charWidth, fontMetrics().height(),
                                                    Qt::AlignRight, "E");
            }
        }


        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }
}

void CodeEditor::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
        handleNewLine();
        if(mainWindow->tabManager->toolsSettings->currentTheme == "Light"){
            QTextCharFormat format;
            format.setForeground(QColor(40, 44, 52)); // 设置字体颜色
            mergeCurrentCharFormat(format);
        }
        else {
            QTextCharFormat format;
            format.setForeground(QColor("white")); // 设置字体颜色
            mergeCurrentCharFormat(format);
        }
    } else if (event->key() == Qt::Key_ParenLeft || event->key() == Qt::Key_BraceLeft || event->key() == Qt::Key_BracketLeft || event->key() == Qt::Key_QuoteDbl) {
        autoCompleteBracket(event);
    } else {
        QPlainTextEdit::keyPressEvent(event);
    }

    // 对于可能改变光标位置或删除字符的按键，都触发括号匹配高亮
    if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right ||
        event->key() == Qt::Key_Up || event->key() == Qt::Key_Down ||
        event->key() == Qt::Key_Home || event->key() == Qt::Key_End ||
        event->key() == Qt::Key_PageUp || event->key() == Qt::Key_PageDown ||
        event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete ||
        event->key() == Qt::Key_ParenLeft || event->key() == Qt::Key_BraceLeft ||
        event->key() == Qt::Key_BracketLeft || 
        event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
        highlightMatchingBrackets();
    }

    if(event->key() == Qt::Key_Backspace) {
        if(mainWindow->tabManager->toolsSettings->currentTheme == "Light"){
            QTextCharFormat format;
            format.setForeground(QColor(40, 44, 52)); // 设置字体颜色
            mergeCurrentCharFormat(format);
        }
        else {
            QTextCharFormat format;
            format.setForeground(QColor("white")); // 设置字体颜色
            mergeCurrentCharFormat(format);
        }
    }
}

int CodeEditor::blockNumberAt(int y) {
    QTextBlock block = firstVisibleBlock();
    int blockNumber = block.blockNumber();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bottom = top + (int) blockBoundingRect(block).height();
    while (block.isValid() && top <= y) {
        if (block.isVisible() && bottom >= y) {
            return blockNumber;
        }

        block = block.next();
        top = bottom;
        bottom = top + (int) blockBoundingRect(block).height();
        ++blockNumber;
    }

    return -1;
}

void LineNumberArea::mouseMoveEvent(QMouseEvent *event) {
    int lineNumber = codeEditor->blockNumberAt(event->pos().y());

    for (const auto &info : codeEditor->syntaxHighlighter->errorInfo) {
        if (info.first.first == lineNumber + 1) {
            QToolTip::showText(event->globalPos(), info.second + "\n（右键取消错误提示）", this);
        } else {
            //QToolTip::hideText();
        }
    }

    QWidget::mouseMoveEvent(event);
}

void LineNumberArea::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::RightButton) {
        int lineNumber = codeEditor->blockNumberAt(event->pos().y());
        for (auto &info : codeEditor->syntaxHighlighter->errorInfo) {
            if (info.first.first == lineNumber + 1) {
                info.first.first = -1;
                update();
                codeEditor->syntaxHighlighter->rehighlight();
            }
        }

    }
    QWidget::mousePressEvent(event);
}

void CodeEditor::wheelEvent(QWheelEvent *event)  {
    if(mainWindow && mainWindow->tabManager && mainWindow->tabManager->toolsSettings);
    else {
        QPlainTextEdit::wheelEvent(event);
        return;
    }
    if (event->modifiers() & Qt::ControlModifier) {
        if (event->angleDelta().y() > 0) {
            int size = mainWindow->tabManager->toolsSettings->currentFont.pixelSize();
            if(++size > 72) size--;
            mainWindow->tabManager->toolsSettings->currentFont.setPixelSize(size);
            mainWindow->tabManager->toolsSettings->fontSizeSpinBox->setValue(size);
            mainWindow->tabManager->on_toolsSettingAccepted();
        } else if (event->angleDelta().y() < 0) {
            int size = mainWindow->tabManager->toolsSettings->currentFont.pixelSize();
            if(--size < 8) size++;
            mainWindow->tabManager->toolsSettings->currentFont.setPixelSize(size);
            mainWindow->tabManager->toolsSettings->fontSizeSpinBox->setValue(size);
            mainWindow->tabManager->on_toolsSettingAccepted();
        }
        event->accept();
    } else {
        QPlainTextEdit::wheelEvent(event);
    }
}


void CodeEditor::paintEvent(QPaintEvent *event)
{
    QPainter painter(viewport()); // 创建 QPainter 对象
    if (true) {
        //std::cout << opacity << std::endl;
        painter.setOpacity(1 - opacity); // 设置不透明度
        // 计算背景图片的中心位置
        //painter.drawPixmap(0, 0, width(), height(), *backgroundImage); // 绘制背景图片
        if(mainWindow->tabManager->toolsSettings->currentTheme == "Light")
            painter.fillRect(viewport()->rect(), QColor(255, 255, 255));  // 绘制蒙版
        else
            painter.fillRect(viewport()->rect(), QColor(36, 36, 41));  // 绘制蒙版
    }
    QPlainTextEdit::paintEvent(event); // 调用基类的 paintEvent 以绘制文本
}

void CodeEditor::handleNewLine()
{
    QTextCursor cursor = textCursor();
    int position = cursor.position();
    
    // 获取当前行光标之前的文本
    cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
    QString lineTextBeforeCursor = cursor.selectedText();

    // 获取光标后的字符
    QChar charAfterCursor = document()->characterAt(position);

    // 获取当前行的缩进
    QString indentation;
    for (QChar ch : lineTextBeforeCursor) {
        if (ch.isSpace()) {
            indentation += ch;
        } else {
            break;
        }
    }

    // 插入新行和缩进
    cursor.setPosition(position);  // 恢复光标位置

    if (lineTextBeforeCursor.trimmed().endsWith('{') && charAfterCursor == '}') {
        // 如果光标在 {} 之间，插入两个新行
        cursor.insertBlock();
        cursor.insertText(indentation + "\t");  // 增加一级缩进
        int middlePosition = cursor.position();
        cursor.insertBlock();
        cursor.insertText(indentation);
        cursor.setPosition(middlePosition);  // 将光标移动到中间行
    } else {
        cursor.insertBlock();
        cursor.insertText(indentation);
        // 如果光标之前的文本以 '{' 结尾，增加一级缩进
        if (lineTextBeforeCursor.trimmed().endsWith('{')) {
            cursor.insertText("\t");
        }
    }

    setTextCursor(cursor);
}

void CodeEditor::autoCompleteBracket(QKeyEvent *event)
{
    QTextCursor cursor = textCursor();
    QString leftBracket = event->text();
    QChar rightBracket = getMatchingBracket(leftBracket[0]);
    
    cursor.insertText(leftBracket);
    cursor.insertText(QString(rightBracket));
    cursor.movePosition(QTextCursor::Left);
    setTextCursor(cursor);
}

void CodeEditor::highlightMatchingBrackets()
{
    bracketSelections.clear();

    QTextCursor cursor = textCursor();
    QTextDocument *document = this->document();

    int leftPosition = cursor.position() - 1;
    int rightPosition = cursor.position();

    QChar leftChar = (leftPosition >= 0) ? document->characterAt(leftPosition) : QChar();
    QChar rightChar = (rightPosition < document->characterCount()) ? document->characterAt(rightPosition) : QChar();

    // 检查左侧和右侧字符
    if (isBracket(leftChar) || isBracket(rightChar)) {
        QChar bracket = isBracket(leftChar) ? leftChar : rightChar;
        int bracketPosition = isBracket(leftChar) ? leftPosition : rightPosition;
        bool searchForward = isOpeningBracket(bracket);

        QString matchingBracketStr = getMatchingBracket(bracket);
        QChar matchingBracket = matchingBracketStr.isEmpty() ? QChar() : matchingBracketStr[0];

        QTextCursor matchCursor = cursor;
        matchCursor.setPosition(bracketPosition);
        int nestingLevel = 1;

        while (nestingLevel > 0 && ((searchForward && !matchCursor.atEnd()) || (!searchForward && !matchCursor.atStart()))) {
            if (searchForward) {
                matchCursor.movePosition(QTextCursor::NextCharacter);
            } else {
                matchCursor.movePosition(QTextCursor::PreviousCharacter);
            }

            QChar currentChar = document->characterAt(matchCursor.position());

            if (currentChar == bracket) {
                nestingLevel++;
            } else if (currentChar == matchingBracket) {
                nestingLevel--;
            }
        }

        if (nestingLevel == 0) {
            highlightBracket(bracketPosition);
            highlightBracket(matchCursor.position());
        }
    }

    setExtraSelections(bracketSelections);
}

void CodeEditor::highlightBracket(int position)
{
    QTextEdit::ExtraSelection selection;
    if(mainWindow->tabManager->toolsSettings->currentTheme == "Light") {
        selection.format.setBackground(QColor("lightGreen"));
        selection.format.setForeground(Qt::black);
    } else {
        selection.format.setBackground(QColor("deepSkyBlue"));
        selection.format.setForeground(Qt::white);
    }


    QTextCursor cursor = textCursor();
    cursor.setPosition(position);
    cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
    selection.cursor = cursor;

    bracketSelections.append(selection);
}

bool CodeEditor::isBracket(QChar ch)
{
    return ch == '(' || ch == '[' || ch == '{' || ch == '<' || ch == ')' || ch == ']' || ch == '}' || ch == '>';
}

bool CodeEditor::isOpeningBracket(QChar ch)
{
    return ch == '(' || ch == '[' || ch == '{' || ch == '<';
}

QChar CodeEditor::getMatchingBracket(QChar bracket)
{
    switch (bracket.unicode())
    {
    case '(':
        return ')';
    case '[':
        return ']';
    case '{':
        return '}';
    case ')':
        return '(';
    case ']':
        return '[';
    case '}':
        return '{';
    case '\"':
        return '\"';
    default:
        return QChar();
    }
}
